﻿using System;
using System.Globalization;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using YSCommander.Data;

namespace YSCommander
{
	/// <summary>
	/// Interaction logic for MainWindow.xaml
	/// </summary>
	public partial class MainWindow : Window
	{
		
		#region Fields

		/// <summary>
		/// Holds the commander data.
		/// </summary>
		private readonly CommanderData data_;

		#endregion Fields

		#region Properties
		#endregion Properties

		#region Methods

		/// <summary>
		/// Creates the instance.
		/// </summary>
		public MainWindow()
		{
			InitializeComponent();

			data_ = new CommanderData();

			data_.LoadData();

			sectionList.ItemsSource = data_.Sections;

			sectionList.SelectedIndex = 0;
		}

		/// <summary>
		/// Handles the closing event - saves the data.
		/// </summary>
		/// <param name="sender">Sender</param>
		/// <param name="e">Event arguments</param>
		private void OnClosing(object sender, System.ComponentModel.CancelEventArgs e)
		{
			data_.SelectedSectionIndex = sectionList.SelectedIndex;
			data_.SelectedProgramIndex = programList.SelectedIndex;
			data_.SaveData();
		}

		/// <summary>
		/// Handles the "add section" button event.
		/// </summary>
		/// <param name="sender">Sender</param>
		/// <param name="e">Event arguments</param>
		private void buttonAddSection_Click(object sender, RoutedEventArgs e)
		{
			var dlg = new SectionWindow
			          	{
							CommanderData = data_
			          	};
			
			if ((bool)dlg.ShowDialog())
			{
				var section = new Section
				              	{
									SectionName = dlg.SectionName
				              	};
				

				if (data_.AddSection(section))
				{
					sectionList.ItemsSource = data_.Sections;

					SelectSectionList(dlg.SectionName);
				}
			}
		}

		/// <summary>
		/// Handles the "section list selection changed" event.
		/// </summary>
		/// <param name="sender">Sender</param>
		/// <param name="e">Event arguments</param>
		private void sectionList_SelectionChanged(object sender, SelectionChangedEventArgs e)
		{
			var index = sectionList.SelectedIndex;

			if (0 <= index)
			{
				programList.ItemsSource = data_.GetPrograms((sectionList.Items[index] as Section).SectionName);

				SetControlsEnabling();
			}
		}

		/// <summary>
		/// Handles the "section list edit" button event.
		/// </summary>
		/// <param name="sender">Sender</param>
		/// <param name="e">Event arguments</param>
		private void buttonEditSection_Click(object sender, RoutedEventArgs e)
		{
			int index = sectionList.SelectedIndex;

			if (0 <= index)
			{
				var section = data_.GetSection((sectionList.Items[index] as Section).SectionName);

				if (null != section)
				{
					var dlg = new SectionWindow
					          	{
									CommanderData = data_,
									SectionName = section.SectionName
					          	};
					
					

					if ((bool)dlg.ShowDialog())
					{
						if (!data_.IsSectionExists(dlg.SectionName))
						{
							data_.DeleteSection(section);
							section.SectionName = dlg.SectionName;
							data_.AddSection(section);
							sectionList.ItemsSource = data_.Sections;

							SelectSectionList(dlg.SectionName);
						}
						else
						{
							MessageBox.Show("The section with this name exists already", Title, MessageBoxButton.OK, MessageBoxImage.Error);
						}
					}
				}
			}
		}

		/// <summary>
		/// Handles the "section list delete" button event.
		/// </summary>
		/// <param name="sender">Sender</param>
		/// <param name="e">Event arguments</param>
		private void buttonDeleteSection_Click(object sender, RoutedEventArgs e)
		{
			int index = sectionList.SelectedIndex;

			if (0 <= index)
			{
				var section = sectionList.Items[index] as Section;
				if (MessageBox.Show(String.Format(CultureInfo.InvariantCulture, "Are you shour you want delete \"{0}\" section?", section.SectionName), 
					Title, MessageBoxButton.YesNo, MessageBoxImage.Question) == MessageBoxResult.Yes)
				{
					data_.DeleteSection(section);
					sectionList.ItemsSource = data_.Sections;
				}
			}
		}

		/// <summary>
		/// Handles the "program list add" button event.
		/// </summary>
		/// <param name="sender">Sender</param>
		/// <param name="e">Event arguments</param>
		private void buttonAddProgram_Click(object sender, RoutedEventArgs e)
		{
			int index = sectionList.SelectedIndex;

			if (0 <= index)
			{
				var section = sectionList.Items[index] as Section;

				var pw = new ProgramWindow
				                   	{
										Section = section,
										Title = "Program"
				                   	};

				if ((bool)pw.ShowDialog())
				{
					var program = new Program
					              	{
										ProgramName = pw.ProgramName,
										ProgramType = ProgramType.Program
					              	};
					
					AddProgram(section, program, index);
				}
			}
		}

		/// <summary>
		/// Adds a program.
		/// </summary>
		/// <param name="section">Section. where to add the program.</param>
		/// <param name="program">The program to add.</param>
		/// <param name="index">Index in the list.</param>
		private void AddProgram(Section section, Program program, int index)
		{
			var wasAdded = false;

			if (!data_.IsProgramExists(section.SectionName, program.ProgramName))
			{
				if (data_.AddProgram(section, program))
				{
					sectionList.ItemsSource = data_.Sections;
					sectionList.SelectedIndex = index;
					programList.ItemsSource = (sectionList.Items[index] as Section).Programs;
					wasAdded = true;
				}
			}

			if (wasAdded)
			{
				SelectProgramList(program.ProgramName);
			}
			else
			{
				MessageBox.Show(String.Format(CultureInfo.InvariantCulture, "Can't add the program \"{0}\". This program name exists already", program.ProgramName),
						Title, MessageBoxButton.OK, MessageBoxImage.Error);
			}
		}

		/// <summary>
		/// Handles the "window loaded" event - clears work folder.
		/// </summary>
		/// <param name="sender">Sender.</param>
		/// <param name="e">Event arguments.</param>
		private void Window_Loaded(object sender, RoutedEventArgs e)
		{
			CommanderData.ClearWorkFolder();

			sectionList.SelectedIndex = data_.SelectedSectionIndex;
			programList.SelectedIndex = data_.SelectedProgramIndex;
		}

		/// <summary>
		/// Handles the "program list selection changed" event.
		/// </summary>
		/// <param name="sender">Sender.</param>
		/// <param name="e">Event arguments</param>
		private void programList_SelectionChanged(object sender, SelectionChangedEventArgs e)
		{
			var index = programList.SelectedIndex;

			var program = (0 <= index) ?
				programList.Items[index] as Program :
				new Program();

			gridProgram.DataContext = program;

			SetControlsEnabling();
		}

		/// <summary>
		/// Handles the "add script" button event.
		/// </summary>
		/// <param name="sender">Sender.</param>
		/// <param name="e">Event arguments.</param>
		private void buttonAddScript_Click(object sender, RoutedEventArgs e)
		{
			var index = sectionList.SelectedIndex;

			if (0 <= index)
			{
				var section = sectionList.Items[index] as Section;

				var pw = new ProgramWindow
				                   	{
										Section = section,
										Title = "Section"
				                   	};

				if ((bool)pw.ShowDialog())
				{
					var program = new Program
					              	{
										ProgramName = pw.ProgramName,
										ProgramType = ProgramType.Script
					              	};

					AddProgram(section, program, index);
				}
			}

			SetControlsEnabling();
		}

		/// <summary>
		/// Handles the "delete program" button event.
		/// </summary>
		/// <param name="sender">Sender.</param>
		/// <param name="e">Event arguments.</param>
		private void buttonDeleteProgram_Click(object sender, RoutedEventArgs e)
		{
			int sectionIndex = sectionList.SelectedIndex;
			int programIndex = programList.SelectedIndex;

			if (0 <= sectionIndex && 0 <= programIndex)
			{
				var section = sectionList.Items[sectionIndex] as Section;
				var program = programList.Items[programIndex] as Program;

				if (MessageBox.Show(String.Format(CultureInfo.InvariantCulture, "Are you sure you want delete \"{0}\" program from \"{1}\" section?",
					program.ProgramName, section.SectionName), Title, MessageBoxButton.YesNo, MessageBoxImage.Question) == MessageBoxResult.Yes)
				{
					CommanderData.DeleteProgram(section, program);

					programList.ItemsSource = data_.GetPrograms(section.SectionName);
				}
			}
		}

		/// <summary>
		/// Handles the "copy program" button event.
		/// </summary>
		/// <param name="sender">Sender.</param>
		/// <param name="e">Event arguments.</param>
		private void buttonCopyProgram_Click(object sender, RoutedEventArgs e)
		{
			var sectionIndex = sectionList.SelectedIndex;
			var programIndex = programList.SelectedIndex;

			if (0 <= sectionIndex && 0 <= programIndex)
			{
				var section = sectionList.Items[sectionIndex] as Section;
				var program = programList.Items[programIndex] as Program;

				var pw = new ProgramWindow
				         	{
								Section = section,
								Title = "Copy",
								ProgramName = program.ProgramName
				         	};
				

				if ((bool)pw.ShowDialog())
				{
					if (data_.CopyProgram(section, program, pw.ProgramName))
					{
						programList.ItemsSource = data_.GetPrograms(section.SectionName);
					}
				}
			}
		}

		/// <summary>
		/// Handles the "Execute" button event.
		/// </summary>
		/// <param name="sender">Sender.</param>
		/// <param name="e">Event arguments.</param>
		private void buttonExecuteProgram_Click(object sender, RoutedEventArgs e)
		{
			ExecuteProgramOrScript();
			
		}

		/// <summary>
		/// Handles the "program location text changed" event.
		/// </summary>
		/// <param name="sender">Sender.</param>
		/// <param name="e">Event arguments.</param>
		private void textBoxProgramLocation_TextChanged(object sender, TextChangedEventArgs e)
		{
			SetControlsEnabling();
		}

		/// <summary>
		/// Handles the "clear work folder" menu item.
		/// </summary>
		/// <param name="sender">Sender.</param>
		/// <param name="e">Event arguments.</param>
		private void menuClearWorkFolder_Click(object sender, RoutedEventArgs e)
		{
			CommanderData.ClearWorkFolder();
		}

		/// <summary>
		/// Handles the "about" menu item.
		/// </summary>
		/// <param name="sender">Sender.</param>
		/// <param name="e">Event arguments.</param>
		private void menuAbout_Click(object sender, RoutedEventArgs e)
		{
			(new AboutWindow()).ShowDialog();
		}

		/// <summary>
		/// Handles the "browse location" button event.
		/// </summary>
		/// <param name="sender">Sender.</param>
		/// <param name="e">Event arguments.</param>
		private void buttonBrowseLocation_Click(object sender, RoutedEventArgs e)
		{
			var program = programList.SelectedItem as Program;

			if (null != program)
			{
				var browse = new System.Windows.Forms.OpenFileDialog
				             	{
				             		InitialDirectory = program.Location,
				             		Filter = "Executable files (*.exe;*.bat;*.cmd)|*.exe;*.bat;*.cmd|All files (*.*)|*.*",
				             		FilterIndex = 1,
				             		RestoreDirectory = true
				             	};

				if (browse.ShowDialog() == System.Windows.Forms.DialogResult.OK)
				{
					program.Location = browse.FileName;
					textBoxProgramLocation.Text = program.Location;

					SetControlsEnabling();
				}	
			}
			
		}

		/// <summary>
		/// Handles the "browse start folder" button event.
		/// </summary>
		/// <param name="sender">Sender.</param>
		/// <param name="e">Event arguments.</param>
		private void buttonBrowseStartFolder_Click(object sender, RoutedEventArgs e)
		{
			var program = programList.SelectedItem as Program;

			if (null != program)
			{
				var browse = new System.Windows.Forms.FolderBrowserDialog
				             	{
									ShowNewFolderButton = false,
                                    Description = "Please select a start folder",
                                    SelectedPath = program.StartFolder
				             	};
				
				if (browse.ShowDialog() == System.Windows.Forms.DialogResult.OK)
				{
					program.StartFolder = browse.SelectedPath;
					textBoxProgramStartFolder.Text = program.StartFolder;

					SetControlsEnabling();
				}
			}
		}

		/// <summary>
		/// Selects the section by name.
		/// </summary>
		/// <param name="sectionName">Specifies the section to select.</param>
		private void SelectSectionList(String sectionName)
		{
			for (var i = 0; i < sectionList.Items.Count; ++i)
			{
				if ((sectionList.Items[i] as Section).SectionName.Equals(sectionName))
				{
					sectionList.SelectedIndex = i;
					programList.SelectedIndex = 0;
					break;
				}
			}
		}

		/// <summary>
		/// Selects the program by name.
		/// </summary>
		/// <param name="programName">Specifies the program to select.</param>
		private void SelectProgramList(String programName)
		{
			for (var i = 0; i < programList.Items.Count; ++i)
			{
				if ((programList.Items[i] as Program).ProgramName.Equals(programName))
				{
					programList.SelectedIndex = i;
					break;
				}
			}
		}

		/// <summary>
		/// Sets controls to enable or disable states.
		/// </summary>
		private void SetControlsEnabling()
		{
			var section = sectionList.SelectedItem as Section;
			var program = programList.SelectedItem as Program;

			buttonEditSection.IsEnabled = (null != section);
			buttonDeleteSection.IsEnabled = (null != section);
			buttonAddProgram.IsEnabled = (null != section);
			buttonAddScript.IsEnabled = (null != section);

			buttonCopyProgram.IsEnabled = (null != program);
			buttonDeleteProgram.IsEnabled = (null != program);
			buttonExecuteProgram.IsEnabled = ((null != program )
				&& ((ProgramType.Program == program.ProgramType) ? 
				(0 < textBoxProgramLocation.Text.Length) :
				(0 < textBoxScript.Text.Length)));

			buttonBrowseLocation.IsEnabled = (null != program && ProgramType.Program == program.ProgramType);

			textBoxProgramLocation.IsEnabled = (null != program && ProgramType.Program == program.ProgramType);
			textBoxScript.IsEnabled = (null != program && ProgramType.Script == program.ProgramType);
		}

		/// <summary>
		/// Handles "script text changed" event.
		/// </summary>
		/// <param name="sender">Sender.</param>
		/// <param name="e">Event arguments</param>
		private void textBoxScript_TextChanged(object sender, TextChangedEventArgs e)
		{
			SetControlsEnabling();
		}

		/// <summary>
		/// Handles double click on the program list: executes the program or script.
		/// </summary>
		/// <param name="sender">Sender.</param>
		/// <param name="e">Event arguments.</param>
		private void programList_MouseDoubleClick(object sender, MouseButtonEventArgs e)
		{
			ExecuteProgramOrScript();
		}

		/// <summary>
		/// Executes selected program or script.
		/// </summary>
		public void ExecuteProgramOrScript()
		{
			var program = programList.SelectedItem as Program;

			if (null != program)
			{
				switch (program.ProgramType)
				{
					case ProgramType.Program:
						data_.ExecuteProgram(program);
						break;
					case ProgramType.Script:
						data_.ExecuteScript(program);
						break;
					default:
						System.Diagnostics.Trace.Assert(false, "Unsupported program type.");
						break;
				}
			}
		}

		/// <summary>
		/// Drag and drop handler.
		/// </summary>
		/// <param name="sender">Sender.</param>
		/// <param name="e">Event arguments</param>
		private void programList_DragOver(object sender, DragEventArgs e)
		{
			if (0 <= sectionList.SelectedIndex && null != e.Data.GetData(DataFormats.FileDrop))
			{
				e.Effects = DragDropEffects.Copy;
			}
		}

		/// <summary>
		/// Drag and drop handler.
		/// </summary>
		/// <param name="sender">Sender.</param>
		/// <param name="e">Event arguments</param>
		private void programList_DragLeave(object sender, DragEventArgs e)
		{
			if (0 <= sectionList.SelectedIndex && null != e.Data.GetData(DataFormats.FileDrop))
			{
				e.Effects = DragDropEffects.None;
			}
		}

		/// <summary>
		/// Drag and drop handler.
		/// </summary>
		/// <param name="sender">Sender.</param>
		/// <param name="e">Event arguments</param>
		private void programList_Drop(object sender, DragEventArgs e)
		{
			var fileNames = (e.Data.GetData(DataFormats.FileDrop) as string[]);

			if (null != fileNames)
			{
				var index = sectionList.SelectedIndex;

				if (0 <= index)
				{
					foreach (var fileName in fileNames)
					{
						var section = sectionList.SelectedItem as Section;

						if (null != section)
						{
							var program = new Program
							              	{
												ProgramType = ProgramType.Program,
                                                ProgramName = System.IO.Path.GetFileNameWithoutExtension(fileName),
                                                Location = fileName
							              	};
							
							AddProgram(section, program, index);
						}
					}
				}
			}

			e.Handled = true;
		}

		#endregion Methods

	}
}
